﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotSpatial.Data;
using System.Data;
using DotSpatial.Topology;
using System.Windows.Forms;

namespace GeostatisticalTool.Classes
{
    public class CheckDataInput 
    {
        private double meanValue = 0;
        private double standarDev = 0;
        private string trans;
        private string field;
        public IFeatureSet data=null;
        public IFeatureSet _originalData;
        private bool filter;

        public string Trans
        {
            get { return trans; }
            set { trans = value; }
        }
        public string Field
        {
            get { return field; }
            set { field = value; }
        }

        public IFeatureSet Data
        {
            get { return data; }
            set { data = value; }
        }

        public double StandarDev
        {
            get { return standarDev; }
            set { standarDev = value; }
        }

        public double MeanValue
        {
            get { return meanValue; }
            set { meanValue = value; }
        }

        public CheckDataInput(IFeatureSet originalData, string field, string trans)
        {
            this._originalData = originalData;
            this.field = field;
            this.trans = trans;
        
        }

        public CheckDataInput(IFeatureSet originalData, string field, string trans, bool filter)
        {
            this._originalData = originalData;
            this.field = field;
            this.trans = trans;
            this.filter = filter;


        }

        public string[] LoadPoints(bool noCheck)
        {
            if (_originalData == null)
                return new string[1] { "Original data is null" };

            if (_originalData.DataTable.Columns["Repeat"] == null)
            {

                _originalData.DataTable.Columns.Add(new DataColumn("Repeat", typeof(string)));
            }
            else
            {
                _originalData.DataTable.Columns.Remove(_originalData.DataTable.Columns["Repeat"]);
                _originalData.DataTable.Columns.Add(new DataColumn("Repeat", typeof(string)));
            }
            data = new FeatureSet(FeatureType.Point);
            data.Projection = _originalData.Projection;
            data.DataTable.Columns.Add(new DataColumn("Measured", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("Trans", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("Trend", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("Predicted", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("Error", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("StdError", typeof(double)));
            data.DataTable.Columns.Add(new DataColumn("Used", typeof(double)));

            string[] problems = new string[2];
            if (noCheck)
            {
                DontCheck();
                return new string[0] { };
            }

            if (!this.filter)
                UpdateDataFeature(problems);
            else
                UpdateDataFeatureFiltering(problems);

            return problems;
        }

        private void DontCheck()
        {
              Stat stat = new Stat(false);

              foreach (Feature fea1 in _originalData.Features)
              {
                  int i = 0;
                  IFeature newFea = data.AddFeature(fea1);
                  newFea.DataRow["Measured"] = fea1.DataRow[field];
                  newFea.DataRow["Trans"] = Transform(trans, Convert.ToDouble(fea1.DataRow[field]));
                  stat += new Stat(Convert.ToDouble(fea1.DataRow[field]));
                 
                 
              }
              if (stat.num > 0)
              {
                  this.meanValue = stat.Mean;//sumAllValues / nRegisters;
                  this.standarDev = stat.StdDevS; //Math.Sqrt((quad - (2 * sumAllValues * this.meanValue) + (nRegisters * this.meanValue * this.meanValue)) / nRegisters);
              }

        }


        private void UpdateDataFeatureFiltering(string[] problems)
        {
            Stat stat = new Stat(false);
            foreach (Feature fea1 in _originalData.Features)
            {
                int i = 0;
                double sum = 0;

                if (!fea1.DataRow["Value"].Equals(null) && Convert.ToString(fea1.DataRow["Variable"])==field)
                {

                    if (Convert.ToString(fea1.DataRow["Repeat"]) != "R")
                    {

                        foreach (Feature fea2 in _originalData.Features)
                        {
                            if (!fea2.DataRow["Value"].Equals(null) && Convert.ToString(fea1.DataRow["Variable"]).Equals(field))
                            {
                                if (fea1.BasicGeometry.Coordinates[0].X == fea2.BasicGeometry.Coordinates[0].X &&
                                 fea1.BasicGeometry.Coordinates[0].Y == fea2.BasicGeometry.Coordinates[0].Y)
                                {
                                    fea2.DataRow["Repeat"] = "R";
                                    i++;
                                    try
                                    {
                                        sum += Convert.ToDouble(fea1.DataRow["Value"]);
                                    }
                                    catch
                                    {
                                        problems[0] = "Empty value";
                                    }
                                }
                            }
                        }

                        try
                        {
                            if (!double.IsNaN(Transform(trans, sum / i)))
                            {
                                IFeature newFea = data.AddFeature(fea1);
                                newFea.DataRow["Measured"] = sum / i;
                                newFea.DataRow["Trans"] = Transform(trans, sum / i);
                                //sumAllValues += (sum / i);
                                //quad += ((sum / i) * (sum / i));
                                // nRegisters++;
                                stat += new Stat((sum / i));
                            }
                            else
                            {
                                problems[1] = "Transformation problem (Not zero values allowed)";
                            }
                        }
                        catch
                        {

                        }
                    }
                }
            }
            if (stat.num > 0)
                this.meanValue = stat.Mean;//sumAllValues / nRegisters;
            this.standarDev = stat.StdDevS; //Math.Sqrt((quad - (2 * sumAllValues * this.meanValue) + (nRegisters * this.meanValue * this.meanValue)) / nRegisters);
        }



        public virtual void UpdateDataFeature(string[] problems)
        {
            Stat stat = new Stat(false);
            foreach (Feature fea1 in _originalData.Features)
            {
                int i = 0;
                double sum = 0;

                if (fea1.DataRow[field] != null)
                {

                    if (Convert.ToString(fea1.DataRow["Repeat"]) != "R")
                    {




                        foreach (Feature fea2 in _originalData.Features)
                        {
                            if (fea2.DataRow[field] != null)
                            {
                                if (fea1.BasicGeometry.Coordinates[0].X == fea2.BasicGeometry.Coordinates[0].X &&
                                 fea1.BasicGeometry.Coordinates[0].Y == fea2.BasicGeometry.Coordinates[0].Y)
                                {
                                    fea2.DataRow["Repeat"] = "R";
                                    i++;
                                    try
                                    {
                                        sum += Convert.ToDouble(fea1.DataRow[field]);
                                    }
                                    catch
                                    {
                                        problems[0] = "Empty value";
                                    }
                                }
                            }
                        }

                        try
                        {
                            if (!double.IsNaN(Transform(trans, sum / i)))
                            {
                                IFeature newFea = data.AddFeature(fea1);
                                newFea.DataRow["Measured"] = sum / i;
                                newFea.DataRow["Trans"] = Transform(trans, sum / i);
                                //sumAllValues += (sum / i);
                                //quad += ((sum / i) * (sum / i));
                                // nRegisters++;
                                stat += new Stat((sum / i));
                            }
                            else
                            {
                                problems[1] = "Transformation problem (Not zero values allowed)";
                            }
                        }
                        catch
                        {

                        }
                    }
                }
            }
            if (stat.num > 0)
                this.meanValue = stat.Mean;//sumAllValues / nRegisters;
            this.standarDev = stat.StdDevS; //Math.Sqrt((quad - (2 * sumAllValues * this.meanValue) + (nRegisters * this.meanValue * this.meanValue)) / nRegisters);
        }

        public double Transform(string type, double value)
        {
            if (type == "None")
                return value;
            if (type == "Log")
            {
                if (value == 0)
                    return double.NaN;

                return Math.Log(value);
            }
            return value;
        }

        public double TransformInverse(string type, double value)
        {
            if (type == "None")
                return value;
            if (type == "Log")
            {

                return Math.Exp(value);
            }
            return value;
        }

    }
}
